% parse notefiles for protocols
% P. manis, 10/28/99
% A completely new version...
%
% The return is a structure of the following form:
%
% 		protocol -> protocol is an array structure itself, as follows:
%		protocol(n).proto	the name of the protocol
%		protocol(n).seq		the sequence that was to be run
%		protocol(n).mode
%		protocol(n).frec		the first record in the protocol
%		protocol(n).lrec		the last record in the protocol
%		protocol(n).ztime		the starting time of the protocol in ztime ( set to 0 here; can be set later when data file is read)
%		protocol(n).etime		the starting time of the protocol in "real time" (read from notefile)
%		protocol(n).valve		The valve setting (initialized at 1)
%		protocol(n).notes		the concatenation of note entries since the last protocol
%	
function [protocol, err] = note_read(filename)
protocol = [];

		protocol.proto=[];		%the name of the protocol
		protocol.seq=[];		%the sequence that was to be run
		protocol.mode=[];		% the type of data acquisition that was done
		protocol.ngrp=[];		% the number of records in each "group" (data, take)
		protocol.frec=[];		%the first record in the protocol
		protocol.lrec=[];		%the last record in the protocol
		protocol.ztime=[];		%the starting time of the protocol in ztime ( set to 0 here; can be set later when data file is read)
		protocol.etime=[];		%the starting time of the protocol in "real time" (read from notefile)
		protocol.valve=[];		%The valve setting (initialized at 1)
		protocol.notes=[];		%the concatenation of note entries since the last protocol
err = 0;

fid = fopen(filename, 'r');
if(fid == -1)
    disp(sprintf('Note File not found: %s',filename))
    err = 1;
    return
end

note_mode = 0; % specifies the internal structure of the notefile
% find the date of the file - this affects how we might read the protocols - dates are approximate
% and may need to be adjusted
[path, file, ext, ver] = fileparts(filename);
da=str2num(file(1:2));
mon=str2num(file(3:5));
yr=str2num(file(6:7));

if(yr >= 96) note_mode = 2; end;

% read the file until get to the first line with a record number identifer on it
% read the number, and set the offset flag to handle different versions of the notes
lctr = 0;
add1 = 0;

while(~feof(fid))
    line = fgetl(fid);
    if(~isempty(line) & (line == -1))
        fclose(fid);
        return;
    end
	lctr = lctr+1;
    [rec, etime, ok] = getrec_2(line);
    if(ok == 1) % got a record, check it
        if(rec == 0) add1 = 1; % set addition flag according to the first record found
        else add1 = 0;
        end
  %      disp(sprintf('set add1: %d', add1))
        break; % get out of the loop
    end
end
%disp(sprintf('First rec: %d on line %d', rec, lctr))
% now read each line in the file
np=0;
lineno=1;
store=0;
latest.lineno=0;
latest.rec=1;
latest.time=[];
latest.note=[];

latest.stim=[];
latest.next_stim=[];
latest.seq=[];
latest.next_seq=[];
latest.frec=1;
latest.next_frec=1;
latest.lrec=1;
latest.next_lrec=1;
latest.valve=1;
latest.next_valve=1;
latest.mode=[];
latest.next_mode=[];
latest.N=0;
latest.next_N=0;

In_Acq=0; % 0 when not in acquisition, 1 when in acqusition, 2 when done with acqusition but not flushed yet.
% NOTE that when we encounter a NOTE, and we are in Acquisition, we act as if we have In_Acq == 2

while (~feof(fid)) % read the whole file, one token at a time.
%	disp('*')
	[tok, line, lineno]=next_token(line, lineno, fid); % get token from input; return remainder of input line.
	if(isempty(tok)) % is end of file if no more tokens
		break;
	end;
	if(istime(tok))
		latest.time=tok;
	end;
	if(isrec(tok))
		latest.rec=getrec(tok,latest.rec);
	end;
	if(iscmd(tok))
		cmd=getcmd(tok);
		switch cmd		
		case {'g', 'get'} % get the stimulus file
			[tok, line, lineno] = next_token(line, lineno, fid);
			if(isempty(tok))
				break;
			end;
			[tok, line, lineno] = next_token(line, lineno, fid);
			if(isempty(tok))
				break;
			end;
			a=findstr(tok, '.');
			if(~isempty(a)) % an extension was present
				tok=tok(1:(a-1)); % this removes the extension...
			end;
			if(~In_Acq) % keep from overwriting when we get several new ones in sequence without doing anything
				latest.stim=tok; % latest.next_stim; % store previous stimulus.
			end;
			if(In_Acq)
				[protocol, np, latest] = sto(protocol, np, latest);
				In_Acq=0;					
			end;
			latest.next_stim=tok;	% when in acquisition (not dumped yet) we just store the latest value.
%			disp(sprintf('latest.time: %s line no: %d Token: %s', latest.time, lineno, tok));
		case 'dsc' % scope - skip
		case 'pulse'
			latest.next_frec=latest.rec; % just update the next_frec;
		case 'do' % do a sequence
			[tok, line, lineno] = next_token(line, lineno, fid);
			if(isempty(tok))
				break;
			end;
			[tok, line, lineno] = next_token(line, lineno, fid);
			if(isempty(tok))
				break;
			end;
			if(~In_Acq) % keep from overwriting when we get several new ones in sequeince without doing anything
				latest.stim=tok; % latest.next_stim; % store previous stimulus.
			end;
			latest.next_stim=tok;	% when in acquisitoin (not dumped yet) we just store the latest value.

			% search for the sequence - it may be a bit forward of where we are.
			[seqc, line, lineno] = find_token('ch:', line, lineno, fid);
			if(isempty(seqc))
				break;
			end;
			[chan, line, lineno] = next_token(line, lineno, fid);
			
			latest.seq=latest.next_seq; % save previous
			[latest.next_seq, line, lineno] = next_token(line, lineno, fid); % get the new one
			if(isempty(latest.next_seq))
				break;
			end;
			latest.lrec=latest.rec-1; % get the current record number
			latest.next_frec=latest.rec; % and the likely next record for storage.
			[RL, err] = record_parse(latest.next_seq); 
			if(~err)
				latest.next_lrec=latest.next_frec+length(RL)-1; % this assumes that the protocol runs to completion.
			end;
			% now get the sequence MODE
			[modec, line, lineno] = find_token('MODE:', line, lineno, fid);
			if(isempty(modec))
				break;
			end;
			[s_mode, line, lineno] = next_token(line, lineno, fid);
			if(isempty(s_mode))
				break;
			end;
			latest.mode=latest.next_mode;
			latest.next_mode=s_mode;
			[n_mode, line, lineno] = next_token(line, lineno, fid);
			if(isempty(n_mode))
				latest.next_N=[];
				break;
			end;
			latest.N=latest.next_N; % save previous
			latest.next_N=str2num(n_mode);
			latest
			In_Acq=In_Acq+1; % note - we're in acquisition now. (? again...)
			
% then we can write out previous protocol from here if it hasn't already been done. We should be current at this point.
			if(In_Acq==2)
				[protocol, np, latest] = sto(protocol, np, latest);
				In_Acq=1;
			end;

			
		case 'seq' % execute a sequence			
			% search for the sequence - it may be a bit forward of where we are.
%			disp(sprintf('In Seq at %s', latest.time))
			[seqc, line, lineno] = find_token('seq:', line, lineno, fid);
			if(isempty(seqc))
				break;
			end;
			latest.seq=latest.next_seq; % save previous
			[latest.next_seq, line, lineno] = next_token(line, lineno, fid); % get the new one
			if(isempty(latest.next_seq))
				break;
			end;
			latest.lrec=latest.rec-1; % get the current record number
			latest.next_frec=latest.rec; % and the likely next record for storage.
			[RL, err] = record_parse(latest.next_seq); 
			if(~err)
				latest.next_lrec=latest.next_frec+length(RL)-1; % this assumes that the protocol runs to completion.
			end;
			% now get the sequence MODE
			[modec, line, lineno] = find_token('MODE:', line, lineno, fid);
			if(isempty(modec))
				break;
			end;
			[s_mode, line, lineno] = next_token(line, lineno, fid);
			if(isempty(s_mode))
				break;
			end;
			latest.mode=latest.next_mode;
			latest.next_mode=s_mode;
			[n_mode1, line, lineno] = next_token(line, lineno, fid);
			l=length(n_mode1);
			n_mode='';
			i=1;
			while(i <= l & findstr(n_mode1(i), '1234567890.+-'))
				n_mode=strcat(n_mode, n_mode1(i));
				i=i+1;
			end;
			if(isempty(n_mode))
				latest.next_N=[];
				break;
			end;
			latest.N=latest.next_N; % save previous
			latest.next_N=str2num(n_mode);
			In_Acq=In_Acq+1; % note - we're in acquisition now. (? again...)
%			latest			
% then we can write out previous protocol from here if it hasn't already been done. We should be current at this point.
			if(In_Acq >= 1)
				[protocol, np, latest] = sto(protocol, np, latest);
				In_Acq=1;
			end;
						
		case 'vo' % set the stim voltage
			
		case 'take' % do a take
			[takec, line, lineno] = find_token('TAKING', line, lineno, fid);
			if(isempty(takec))
				break;
			end;
			[s_take, line, lineno] = next_token(line, lineno, fid);
			if(isempty(s_take))
				break;
			end;
			latest.next_N=str2num(s_take);
			if(~strcmp(latest.mode, 'take')) % if we just switched modes...
				latest.frec=latest.rec; % then save the first record
			end;
			if(~In_Acq)
				latest.mode='take';
				end;
			latest.next_mode='take';
			In_Acq=1;
						
		case 'da'	% do a da...
			latest.mode='da';
			latest.frec=latest.rec;

		case 'ave'
			latest.mode = 'average';
			latest.frec=latest.rec;		

		case {'v1','v2','v3','v4'} % valve selection
			latest.valve=latest.next_valve; % push previous valve setting.
			latest.next_valve=str2num(cmd(2)); 
%			latest.next_frec=latest.rec; % save most recent record...
			latest.lrec=latest.rec-1;
			if(In_Acq)
				[protocol, np, latest] = sto(protocol, np, latest);
				In_Acq=0;					
			end;
		case 'note'	% pick up the note.
			note=[];
			tok=[];
			while(~istime(tok) & ~feof(fid))
				[tok, line, lineno] = next_token(line, lineno, fid);
				if(~istime(tok))
					note=[note ' ' tok];
				end;
			end;
			if(istime(tok))
				latest.time=tok;
			end;
%disp(sprintf('?Note: at %s, In_Acq=%d', latest.time, In_Acq'))
% then we can write out previous protocol from here if it hasn't already been done. We should be current at this point.
			if(In_Acq > 1) % act as if we are in 1 or 2 (done with acquisition)
				[protocol, np, latest] = sto(protocol, np, latest);
				In_Acq=0; % we are in a NOTE: there is no acquisition going on.
			end;
			latest.note = strvcat(latest.note, note);
			

		otherwise
		end;
	end;	
%	disp(sprintf('%d', lineno))
	latest.lineno=lineno;
end; % of while loop

fclose(fid);
if(In_Acq)
	latest.lrec=latest.rec-1;
	[protocol, np, latest] = sto(protocol, np, latest);
	In_Acq=0;
end;

%np1=np;
%for np=1:np1
%		disp(sprintf('T: %s  V: %d R: %d-%d  STM: %s  seq: %s  mode: %s %d', protocol(np).etime, protocol(np).valve, protocol(np).frec, protocol(np).lrec, ...
%		    protocol(np).proto, protocol(np).seq, protocol(np).mode, protocol(np).N))
%end;
return;

function [protocol, np, latest] = sto(protocol, np, latest)
		if(np>=1) % do the protection (restart) thing.
			if(latest.frec > protocol(np).frec)
				np=np+1;
			else % records did not advance. only store if lrec > last lrec, but store in place.
				if(latest.lrec < protocol(np).lrec)
					return;
				end; % note that this falls through without incrementing and overwrites np if latest.lrec >= p(np).lrec
			end;
		else % here only when np=0 - just start things.
			np=1;
		end;
		protocol(np).mode=latest.mode;
		protocol(np).N=latest.N;
		protocol(np).frec=latest.frec;
		protocol(np).lrec=latest.lrec;
		protocol(np).valve=latest.valve;
		protocol(np).etime=latest.time;
		protocol(np).seq=latest.seq;
		protocol(np).proto=latest.stim;
		protocol(np).ztime=0;
		protocol(np).notes=latest.note;

		latest.stim=latest.next_stim; 
		latest.seq=latest.next_seq;
		latest.mode=latest.next_mode;
		latest.valve=latest.next_valve;
		latest.frec=latest.next_frec;
		latest.lrec=latest.next_lrec;
		latest.N=latest.next_N;
		latest.note=[]; % reset the notes...
return;


function [tok, remline, lineno] = find_token(token, line, lineno, fid)
% function to search forward for a particular token in the file.
	tok=[];
	while(isempty(tok))
		[tok, remline, lineno] = next_token(line, lineno, fid);
		line=remline;
%		disp(sprintf('tok: %s  token: %s', tok, token))
		if(strcmp(tok, token))
			return;
		end;
		if(feof(fid)) % we hit the end of the file without finding it.
			return;
		end;
		tok=[]; % keep it empty to keep search going.
	end;
return;

function[tok, remline, lineno]=next_token(line, lineno, fid)
	tok=[];
	while(isempty(tok))
		[tok, remline]=strtok(line,' ');
		line=remline;
%		tok=deblank(tok); % make sure its "empty"...
		if(isempty(tok)) % still empty? then...
			line=fgetl(fid); % get the new line
			if(feof(fid)) % end of file there - no good
				return; % with tok empty, means end of file.
			end
			lineno=lineno+1;
		end
	end	
return;

function [yes] = iscmd(s)
yes=0;
s=deblank(fliplr(deblank(fliplr(s))));
if(s(1)=='>' & length(s)>=2)
	yes=1;
	return;
end;

function [cmd] = getcmd(s)
	cmd=[];
	if(~iscmd(s))
		return;
	end;
	cmd=s(2:length(s));
	return;

function [yes] = isrec(s)
	yes=0;
	if(length(s)>=4)
		if(strcmp(s(1:3),'[R:'))
			yes=1;
			return;
		end;
	end;
return;

function [rec] = getrec(s, l)
rec=l; % always use the PREVIOUS record
a=isrec(s);
e=length(s);
if(s(e)==']')
	e=e-1;
end;
if(isrec(s))
	p=findstr(s,'R:');
	rec=str2num(s(4:e));
	if(isempty(rec))
		rec = l;
	end;
end;
%	disp(sprintf('getrec: isrec=%d s = %s s4=%s rec=%d', a, s, s(4:length(s)), rec)) 
return;


% parse a line for record numbers....
function [rec, etime, ok] = getrec_2(line)
rec = 0;
ok = 0;
etime = '';
pos = findstr(line, 'R:');	% search the line for the record marker
if(isempty(pos))
	return;
end
rec = str2num(line(pos+2:pos+5));
etime = line(1:8);
ok = 1;
return;

function [yes] = istime(s)
% determine whether a string is a time format... if so, say...
	yes=0;
	if(length(s) < 8)
		return;
	end;
	if(s(3)==':' & s(6)==':')
		if(~isletter(s(1:2)) & ~isletter(s(4:5)) & ~isletter(s(7:8)))
		yes=1;
		return;
		end;
	end;
	
